/*
 * CSVFileFormater
 *
 * Copyright (c) 2012, Stephane Cuillerdier
 * All rights reserved.
 * 
 * This software is licensed under the new BSD License:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 * 
 * Neither the name of the author nor the names of its contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * version 1.0
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Threading;

namespace CSVFileFormater
{
    #region Public Delegates

    // delegates used to call MainForm functions from worker thread
    public delegate void DelegateAddConsoleMsg(String s);
    public delegate void DelegateSetProgressValue(int val);
    public delegate void DelegateThreadFinished();

    #endregion

    /// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
        #region Members For Thread

        // worker thread
        Thread m_WorkerThread;

        // events used to stop worker thread
        ManualResetEvent m_EventStopThread;
        ManualResetEvent m_EventThreadStopped;

        string configBoxText;
        string pathBoxText;

        // Delegate instances used to cal user interface functions 
        // from worker thread:
        public DelegateAddConsoleMsg m_DelegateAddConsoleMsg;
        public DelegateSetProgressValue m_DelegateSetProgressValue;
        public DelegateThreadFinished m_DelegateThreadFinished;

        StreamWriter Log;
        
        #endregion

        public ConfigLua cLua;

		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();

            UpdateConfigBox();

            // initialize delegates
            m_DelegateAddConsoleMsg = new DelegateAddConsoleMsg(this.AddConsoleMsg);
            m_DelegateSetProgressValue = new DelegateSetProgressValue(this.SetProgressValue);
            m_DelegateThreadFinished = new DelegateThreadFinished(this.ThreadFinished);

            // initialize events
            m_EventStopThread = new ManualResetEvent(false);
            m_EventThreadStopped = new ManualResetEvent(false);
		}

        private void tableLayoutPanel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (RunBtn.Text == "GO") // on lance le thread
            {
                RunBtn.Text = "STOP";

                ConsoleBox.Items.Clear();

                // reset events
                m_EventStopThread.Reset();
                m_EventThreadStopped.Reset();

                configBoxText = this.ConfigBox.Text;
                pathBoxText = this.PathBox.Text;

                // create worker thread instance
                m_WorkerThread = new Thread(new ThreadStart(this.WorkerThreadFunction));

                m_WorkerThread.Name = "Worker Thread Config Lua";	// looks nice in Output window

                m_WorkerThread.Start();
            }
            else
                if (RunBtn.Text == "STOP") // on stop le thread
                { 
                    RunBtn.Text = "GO";

                    StopThread();
                }
        }

        // OpenFileDialog
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog fDialog = new OpenFileDialog();
            
            fDialog.Title = "Open File";
            fDialog.Filter = "CSV Files|*.csv|All Files|*.*";
            fDialog.AddExtension = true;
            fDialog.CheckFileExists = true;
            fDialog.ShowHelp = true;

            if (fDialog.ShowDialog() == DialogResult.OK)
            {
                PathBox.Text = fDialog.FileName.ToString();
            }
            
        }

        public void UpdateConfigBox()
        {
            string appPath = Path.GetDirectoryName(Application.ExecutablePath);

            string scriptPath = appPath + "\\scripts";

            DirectoryInfo di = new DirectoryInfo(scriptPath);
            FileInfo[] rgFiles = di.GetFiles("*.lua");

            foreach (FileInfo fi in rgFiles)
            {
            	if ( fi != null )
                	ConfigBox.Items.Add(fi.Name);
            }
            if ( ConfigBox.Items.Count != 0 )
            	ConfigBox.SelectedIndex = 0;
        }

        public void AddConsoleMsg(string msg)
        {
            ConsoleBox.Items.Add(msg);
        }

        public void SetProgressValue(int val)
        {
            progressBar.Value = val;
        }

        // Worker thread function.
        // Called indirectly from btnStartThread_Click
        private void WorkerThreadFunction()
        {
            cLua = new ConfigLua(m_EventStopThread, m_EventThreadStopped, this);

            cLua.RunConfig(configBoxText, pathBoxText);
        }

        // Stop worker thread if it is running.
        // Called when user presses Stop button of form is closed.
        private void StopThread()
        {
            if (m_WorkerThread != null && m_WorkerThread.IsAlive)  // thread is active
            {
                // set event "Stop"
                m_EventStopThread.Set();

                // wait when thread  will stop or finish
                while (m_WorkerThread.IsAlive)
                {
                    // We cannot use here infinite wait because our thread
                    // makes syncronous calls to main form, this will cause deadlock.
                    // Instead of this we wait for event some appropriate time
                    // (and by the way give time to worker thread) and
                    // process events. These events may contain Invoke calls.
                    if (WaitHandle.WaitAll(
                        (new ManualResetEvent[] { m_EventThreadStopped }),
                        100,
                        true))
                    {
                        break;
                    }

                    Application.DoEvents();
                }
            }

            ThreadFinished();		// set initial state of buttons
        }

        // Set initial state of controls.
        // Called from worker thread using delegate and Control.Invoke
        private void ThreadFinished()
        {
            RunBtn.Text = "GO";
        }

        private void progressBar_Click(object sender, EventArgs e)
        {

        }

        private void button3_Click(object sender, EventArgs e)
        {
            string appPath = Path.GetDirectoryName(Application.ExecutablePath);
            string scriptPath = appPath + "\\scripts\\";
            string filepath = scriptPath + ConfigBox.Text;

            System.Diagnostics.Process.Start(filepath);

        }
		
        // sauve le contenu de la listbox dans un fichier
		void Button2Click(object sender, EventArgs e)
		{
			int countMsg = ConsoleBox.Items.Count;
			if ( countMsg == 0 ) return;
			
			string LogFilePath = "Save " + DateTime.Now.ToString() + ".log";
			LogFilePath = LogFilePath.Replace('/', '-');
			LogFilePath = LogFilePath.Replace(' ', '_');
			LogFilePath = LogFilePath.Replace(':', '-');

			if (!File.Exists("Save.log"))
            {
                Log = new StreamWriter(LogFilePath);
            }
            else
            {
                Log = File.AppendText(LogFilePath);
            }

            for ( int i=0; i< countMsg; i++ )
            {
            	Log.WriteLine(ConsoleBox.Items[i]);
            }
         
            Log.Close();
		}
		
		void Button4Click(object sender, EventArgs e)
		{
			AboutDlg dlg = new AboutDlg();
			dlg.ShowDialog();
		}
	}
}
